//对文件进行写入操作来打乱文件系统的物理块分布
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>


#define MAX_LINE_SIZE 1024

//这里记录要打乱的程序，数字越大程度越大
#define MAX_WRITE_RANGE 150000

//为了可以保证充分发挥优势，我们当发现不连续的时候，将上一个块的之后一个块进行一次写操作来打乱顺序
//所以不能只处理在记录中有的读请求，而是应该处理记录中读请求之后的请求，打乱那些请求才是有意义的

//每隔一个进行一次写入操作
int main(){
    FILE *fp_read = NULL;
    char line[MAX_LINE_SIZE];

    int fd1;

    fd1=open("test",O_CREAT | O_RDWR,00777);
    if(fd1!=-1){
        printf("file is created.\n");
    }
    
    //循环变量
    long j;
    int i;

    //一个用来记录当前存储位置的变量
    long now_index = 0;

    //这里记录上一次访问的偏移地址
    long last_access = 0;
    //这里记录上一次访问的大小
    long last_size = 0;

    //临时记录当前访问范围的变量
    long begin_temp;
    long size_temp;

    //这里申请写缓冲区和返回值收集
    void* buf = (void *)malloc(4096 + 1);

    memset(buf, 0, 4096 + 1);

    printf("开始运行\n");

    if((fp_read = fopen("fix-tracecsv", "r")) != NULL){
        printf("开始读取\n");

        char delims[] = ",";
        char *result = NULL;

        while (fgets(line, MAX_LINE_SIZE, fp_read)){
            printf("正在扫描第%ld条记录\n", now_index);


            //查看扫描的记录数量，到数量了就要停止
            if(now_index > MAX_WRITE_RANGE){
                //这里导致了停止
                break;
            }
            
            
            //这里是个分割的元素
            result = strtok( line, delims );

            // printf("%s", result);

            //这里要进行计数，只保留第5列
            i = 1;

            if(i == 1){
                begin_temp = atol(result);
                // printf("%ld\n", begin_temp);
            }

            //只要还有可以分的，那result不会是NULL
            while((result = strtok( NULL, delims))){
                i++;
                
                //这里将offset也考虑在内
                if(i == 2){
                    size_temp = atol(result);
                    
                    if(last_access + last_size != begin_temp){
                        //这里说明不是顺序访问，将这个点之后的几个块打乱，打乱的窗口就是上一次的访问size*5，打乱的粒度就是4096
                        int j = 0;
                        int write_offset;
                        for(j = 1 ; j <= last_size * 5 / 4096; j += 2){
                            //这里计算出下一个的函数的窗口
                            write_offset = last_access + last_size + 4096*j;
                            //这里进行打乱，因为系统只支持4k对齐，所以需要屏蔽所有的非4K对齐的offset
                            if(write_offset % 4096 == 0){
                                pwrite(fd1, buf, 4096, write_offset%17179869184);
                            }
                        }
                    }
                }
            }

            //读完之后保存一下历史
            last_access = begin_temp;
            last_size = size_temp;
            
            now_index++;
        }

        printf("写完毕\n");
        free(buf);
        fclose(fp_read);
        close(fd1);

        fp_read = NULL;
    }
}